package com.atguigu.gulimall.order.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.common.utils.R;
import com.atguigu.common.vo.MemberResponseVO;
import com.atguigu.gulimall.order.dao.OrderDao;
import com.atguigu.gulimall.order.entity.OrderEntity;
import com.atguigu.gulimall.order.feign.CartFeignService;
import com.atguigu.gulimall.order.feign.MemberFeignService;
import com.atguigu.gulimall.order.feign.WmsFeignService;
import com.atguigu.gulimall.order.interceptor.LoginUserInterceptor;
import com.atguigu.gulimall.order.service.OrderService;
import com.atguigu.gulimall.order.vo.MemberAddressVO;
import com.atguigu.gulimall.order.vo.OrderConfirmVO;
import com.atguigu.gulimall.order.vo.OrderItemVO;
import com.atguigu.gulimall.order.vo.SkuStockVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author : wenchao.long
 * @date : Created in 2021/8/18 17:18 周三
 * @description :
 */
@Service("orderService")
@AllArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    private final MemberFeignService memberFeignService;

    private final CartFeignService cartFeignService;

    private final ThreadPoolExecutor executor;

    private final WmsFeignService wmsFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    @Override
    public OrderConfirmVO confirmOrder() {
        OrderConfirmVO confirmVO = new OrderConfirmVO();

        MemberResponseVO member = LoginUserInterceptor.loginUser.get();
        Long id = member.getId();

        // 老的请求数据
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        // 异步请求会丢失上下文
        CompletableFuture<Void> getAddressFuture = CompletableFuture.runAsync(() -> {
            // 所以要把新的请求 放入
            RequestContextHolder.setRequestAttributes(requestAttributes);
            // 1. 远程查询所有的收货地址列表
            List<MemberAddressVO> address = memberFeignService.getAddress(id);
            confirmVO.setAddress(address);
        }, executor);


        CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
            // 所以要把新的请求 放入
            RequestContextHolder.setRequestAttributes(requestAttributes);
            // 2. 远程查询购物车所有选中的购物项
            List<OrderItemVO> cartItems = cartFeignService.getCurrentUserCartItems();
            confirmVO.setItems(cartItems);
        }, executor).thenRunAsync(() -> {
            List<OrderItemVO> items = confirmVO.getItems();
            List<Long> collect = items.stream()
                    .map(OrderItemVO::getSkuId)
                    .collect(Collectors.toList());
            R r = wmsFeignService.getSkuHasStocks(collect);
            List<SkuStockVO> stocks = r.getData(new TypeReference<List<SkuStockVO>>() {
            });
            if (stocks != null) {
                Map<Long, Boolean> map = stocks.stream()
                        .collect(Collectors.toMap(SkuStockVO::getSkuId, SkuStockVO::getHasStock));
                confirmVO.setStocks(map);
            }
        }, executor);

        try {
            CompletableFuture.allOf(getAddressFuture, cartFuture).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }


        // 3. 查询用户积分
        Integer integration = member.getIntegration();
        confirmVO.setIntegration(integration);


        // feign调用远程 丢失头 由于创建新的request 去调用别的服务，所以会丢失头部信息
        // 可以 加上feign远程调用的请求拦截器
        // 在 GuliFeignConfig 中配置

        // TODO: 5. 防重令牌

        return confirmVO;
    }

}
